<template>
  <cross-line :text="crossText" v-model:visible="CrossLineVisible" />
  <el-skeleton :loading="false" animated :count="1">
    <template #default>
      <div class="main" v-show="CrossLineVisible">
        <div v-if="mainOperateType == OperateTypes.EDIT" :class="$style.operate">
          <el-button @click="addRow">{{ $t('lang.operate.increase') }}</el-button>
          <confirm
            type="button"
            link-type="danger"
            info-type="error"
            :text="$t('lang.operate.batchDelete')"
            :title="$t('lang.operate.hint')"
            :content="$t('lang.message.deleteRecords')"
            :updateData="handleRefreshData"
            :request-data="() => deleteRecordsRequest(selectedRows.map((d) => d.id))"
            :disabled="selectedRows.length == 0"
          />
        </div>
        <div class="table">
          <el-table
            ref="tableRef"
            border
            :data="dataSource"
            v-loading="tabelLoading"
            max-height="320"
            @selection-change="handleSelectionChange"
            :row-style="{ height: 54 + 'px' }"
            :cell-style="{ padding: 0 + 'px' }"
          >
            <!-- 多选 -->
            <el-table-column v-if="selection" type="selection" width="55" fixed align="center" />
            <!-- 序号 -->
            <el-table-column
              v-if="index"
              type="index"
              :label="$t('lang.table.index')"
              fixed
              align="center"
              :index="handleIndex"
            />
            <column v-for="column of columns" :key="column.key" :item="column" :options="options" />
            <!-- 操作列 -->
            <el-table-column
              v-if="showOperateColumn"
              :label="$t('lang.operate.name')"
              fixed="right"
              align="center"
            >
              <template #default="scope">
                <div class="operate">
                  <!-- <slot :row="scope.row" name="operate" /> -->
                  <expand-operate-buttons
                    :row="scope.row"
                    :action="handleAction"
                    :refresh-data="handleRefreshData"
                    :operateTypesList="subOperateTypesList"
                  />
                </div>
              </template>
            </el-table-column>
          </el-table>
          <el-pagination
            class="pagination"
            v-if="dataPaging"
            v-model:current-page="pagination.pageNum"
            :page-size="pagination.pageSize"
            :page-sizes="pageSizes"
            layout="total, prev, pager, next, jumper"
            :total="pagination.total"
            background
            @current-change="changePage"
            @size-change="handleSizeChange"
            style="margin: 10px 0 0 0"
          />
        </div>
      </div>
      <!-- 操作弹窗 -->
      <OperateModal
        v-model:visible="visible"
        width="1300px"
        :title="title"
        :approval-no="initialValues.approvalNo"
        :succeed-approval="onClose"
        :initial-values="initialValues"
        :operate-type="operateType"
      >
        <template #operate>
          <div v-if="operateType === OperateTypes.ADD" style="margin-right: 10px">
            <!-- <el-button @click="onSubmit" type="primary" plain>
              {{ $t('lang.operate.submit') }}
            </el-button> -->
            <el-button @click="onSave" type="primary" plain>{{
              $t('lang.operate.save')
            }}</el-button>
          </div>
          <div v-else-if="operateType === OperateTypes.EDIT" style="margin-right: 10px">
            <!-- <el-button type="primary" plain @click="updateStatus">
              {{ $t('lang.operate.submit') }}
            </el-button> -->
            <el-button type="primary" plain @click="onEdit">{{
              $t('lang.operate.save')
            }}</el-button>
          </div>
        </template>
        <template #default="{ isOpened }">
          <inspect-maint-tab :show-inspect-records="false">
            <OperateForm
              :cross-text="$t(crossText)"
              :form-items="formItems"
              v-model="params"
              label-width="140px"
              :title="title"
              :options="options"
              :autocompleteOptions="autocompleteOptions"
              :disabled="disabled"
              :is-opened="isOpened"
              :initial-values="initialValues"
            />
            <invoices :data="initialValues" />
          </inspect-maint-tab>
        </template>
      </OperateModal>
    </template>
  </el-skeleton>
</template>

<script lang="ts">
import CrossLine from './CrossLine.vue'
import { computed, PropType, ref, defineComponent, onMounted, toRefs, watch } from 'vue'
import { DataSource, Columns, Pagination } from '@/components/Records/types'
import Column from '@/components/Records/Column.vue'
import { I18nMessageId, ObjectType, ResponseDataPromise } from 'typings/interfaces'
import { Options, FormItems } from '@/components/Form/types'
import { Optional } from 'typings/util'
import { intersectionBy, forEach, differenceBy, fromPairs, map } from 'lodash'
import { useStore } from 'vuex'
import { useRouter } from 'vue-router'
import useSearch from '@/hooks/useSearch'
import useForm from '@/hooks/useForm'
import ExpandOperateButtons from '@/components/ExpandOperateButtons/index.vue'
import OperateModal from '@/components/OperateModal/index.vue'
import OperateForm from '@/components/OperateModal/components/Form.vue'
import { OperateTypes } from '@/enums/operateTypes'
import Confirm from '@/components/Confirm/index.vue'
import useRender from '@/components/OperateModal/hooks/useRender'

type Sort = Optional<Pagination>

interface Order {
  order: 'ascending' | 'descending' | null
  prop: string
}

export default defineComponent({
  emits: {
    'change-page': null,
    'size-change': null,
    onAction: null,
    watchKeyChange: null,
    onRefreshData: null,
  },
  components: {
    CrossLine,
    Column,
    ExpandOperateButtons,
    OperateModal,
    OperateForm,
    Confirm,
  },
  props: {
    idObj: {
      // 草稿状态下，编辑，添加需要的主表的id键值对。
      type: Object as PropType<Record<string, string>>,
      required: true,
    },
    crossText: {
      type: String,
      required: true,
    },
    loading: {
      type: Boolean,
      required: true,
    },
    columns: {
      type: Array as PropType<Columns>,
      required: true,
    },
    formItems: {
      type: Array as PropType<FormItems>,
      required: true,
    },
    // dataSource: {
    //   type: Array as PropType<DataSource>,
    //   required: true,
    // },
    // 非必填
    index: {
      type: Boolean,
      default: true,
    },
    selection: {
      type: Boolean,
      default: true,
    },
    defaultSelectedRows: {
      type: Array as PropType<ObjectType[]>,
      default: [],
    },
    options: {
      type: Object as PropType<Options>,
      default: () => ({}),
    },
    autocompleteOptions: {
      type: Object as PropType<ObjectType>,
      default: () => ({}),
    },
    maxHeight: {
      type: Number,
      default: 500,
    },
    valuePath: {
      type: String,
      default: 'id',
    },
    sort: {
      type: Function as PropType<(obj: Sort) => Promise<ObjectType[]>>,
      required: true,
    },
    sizeChange: {
      type: Function as PropType<(obj: ObjectType) => Promise<any[]>>,
      default: null,
    },
    mainOperateType: {
      type: String,
      default: '',
    },
    tableInitialValues: {
      type: Array as PropType<ObjectType[]>,
      default: [],
    },
    fetchRecordsRequest: {
      type: Function as PropType<(...parmas: any) => ResponseDataPromise<ObjectType>>,
      required: true,
    },
    createRecordRequest: {
      type: Function as PropType<(...parmas: any) => ResponseDataPromise<ObjectType>>,
      required: true,
    },
    editRecordRequest: {
      type: Function as PropType<(...parmas: any) => ResponseDataPromise<ObjectType>>,
      required: true,
    },
    deleteRecordsRequest: {
      type: Function as PropType<(...parmas: any) => ResponseDataPromise<ObjectType>>,
      required: true,
    },
    handleInitialValues: {
      type: Function as PropType<(value: ObjectType) => ObjectType>,
      required: false,
      default: (initValues: ObjectType) => ({
        ...initValues,
      }),
    },
    handleParams: {
      type: Function as PropType<(params: ObjectType, status: 0 | 1) => ObjectType>,
      required: false,
      default: (params: ObjectType, status: 0 | 1) => ({
        ...params,
        status,
      }),
    },
    watchKeyList: {
      type: Array as PropType<string[]>,
      default: [],
    },
    // 数据分页 展示分页数据就设置为true 并且对应fetchDataValuePath为table数据路径，例如'data.records'
    dataPaging: {
      type: Boolean,
      default: false,
    },
    fetchDataValuePath: {
      type: String,
      default: 'data',
    },
    labelWidth: {
      type: String,
      default: '140px',
    },
    showOperateColumn: {
      type: Boolean,
      default: true,
    },
    isOpened: {
      type: Boolean,
      default: true,
    },
    operateTypesList: {
      type: Array as PropType<OperateTypes[]>,
      default: [OperateTypes.EDIT, OperateTypes.VIEW],
    },
  },
  setup(props, { emit }) {
    const store = useStore()
    const router = useRouter()
    const tableRef = ref<ObjectType | null>(null)
    const { isOpened } = toRefs(props)
    const { visible: CrossLineVisible } = useRender(isOpened)

    const { loading, pagination, dataSource, changePage, refreshData } = useSearch(
      props.fetchRecordsRequest,
      {
        notImmediate: false,
        valuePath: props.fetchDataValuePath,
        extraParams: props.idObj,
      }
    )
    const handleRefreshData = (jumpFirstPage?: boolean) => {
      emit('onRefreshData')
      return refreshData(jumpFirstPage)
    }

    const {
      title,
      visible,
      action,
      initialValues,
      request,
      params,
      disabled,
      onClose,
      operateType,
    } = useForm(
      fromPairs(map(props.formItems, ({ key }) => [key, undefined])),
      handleRefreshData,
      props.handleInitialValues
    )
    const handleAction = (type: OperateTypes, titleId: I18nMessageId, initValues: ObjectType) => {
      emit('onAction', { type, titleId, initValues })
      action(type, titleId, { ...initValues })
    }

    // 新增-保存
    const onSave = () =>
      request(() =>
        props.createRecordRequest(props.handleParams({ ...params.value, ...props.idObj }, 0))
      )

    /* 编辑-保存 */
    const onEdit = () =>
      request(() =>
        props.editRecordRequest(props.handleParams({ ...params.value, ...props.idObj }, 0))
      )

    // 初始已选择行
    onMounted(() => {
      if (props.tableInitialValues) {
        dataSource.value = props.tableInitialValues
      }
    })
    const handleIndex = (index: number) => {
      if (props.dataPaging) {
        const { pageNum, pageSize } = pagination
        return (pageNum - 1) * pageSize + index + 1
      }
      return index + 1
    }

    const pageSizes = computed(() => store.state.global.pageSizes)
    const handleSizeChange = (val: number) => {
      store.commit('savePageSize', val)
      emit('size-change', val)
    }
    const addRow = () => {
      handleAction(OperateTypes.ADD, 'lang.operate.add', { ...props.idObj })
    }

    const selectedRows = ref([])
    const removeRows = () => {
      //   console.log('selectedRows', selectedRows.value)
    }

    const handleSelectionChange = (selection) => {
      selectedRows.value = selection
    }

    watch(
      () => props.watchKeyList.map((key) => params.value[key]),
      () => {
        emit('watchKeyChange', params.value)
      }
    )

    const deleteRows = () => {
      return new Promise((resolve, reject) => {
        props
          .deleteRecordsRequest(selectedRows.value.map((d) => d['id']))
          .then(() => {
            resolve(true)
          })
          .catch(() => {
            reject(false)
          })
      })
    }

    const subOperateTypesList = computed(() => {
      if (props.mainOperateType == OperateTypes.EDIT) {
        return [OperateTypes.EDIT, OperateTypes.VIEW]
      }
      return [OperateTypes.VIEW]
    })
    return {
      tableRef,
      changePage,
      //   changePage: (page: number) => emit('change-page', page),
      handleIndex,
      handleSizeChange,
      pageSizes,
      pagination,
      tabelLoading: loading,
      title,
      visible,
      action,
      dataSource,
      initialValues,
      request,
      params,
      disabled,
      onClose,
      operateType,
      OperateTypes,
      onSave,
      onEdit,
      removeRows,
      handleSelectionChange,
      selectedRows,
      addRow,
      handleAction,
      deleteRows,
      handleRefreshData,
      CrossLineVisible,
      subOperateTypesList,
    }
  },
})
</script>
<style module lang="scss">
.operate {
  margin: 10px 0;
}
.error-text {
  span {
    color: #f56c6c;
  }
}
.table {
  display: flex;
  flex-direction: column;
  height: 100%;
  flex: 1;
  :global(.el-pagination) {
    text-align: end;
  }
  .pagination {
    margin-top: auto;
  }
}
</style>
